[Chapter 30] 30.5 Internally Defined Names
Author: Bryan Costales & Eric Allman
Date: 1999-01-06T19:57:20Z

#

| Chapter 30 Delivery Agents |

## 30.5 Internally Defined Names

V8 sendmail internally predefines two delivery agents for the special handling of files (`*file*` and `*include*`) and one for the special handling of errors (`error`).

### 30.5.1 The *file* and *include* Agents

The `*file*` delivery agent (the `*` characters are part of the name) handles delivery to files. The `*include*` delivery agent handles delivery through `:include:` lists. Neither can be considered a real delivery agent, because actual delivery is still handled internally by sendmail. Instead, they provide a way to tune delivery-agent behavior for these two delivery needs.

The predefined defaults for these delivery agents can be viewed with the following command: [13]

> [13] The output lines are unfortunately wrapped at the right margin of this book text.

>     % /usr/lib/sendmail -d0.15 -bt < /dev/null | egrep "file|include"
>     mailer 1 (*file*): P=[FILE] S=0/0 R=0/0 M=0 U=0:0 F=9DEFMPloqsu L=0 E=\n T=DNS/RF
>     C822/X-Unix A=FILE $u
>     mailer 2 (*include*): P=/dev/null S=0/0 R=0/0 M=0 U=0:0 F=su L=0 E=\n T=<undefine
>     d>/<undefined>/<undefined> A=INCLUDE $u

The defaults may be overwritten by declaring these delivery agents in the configuration file. For example, the following configuration file declaration overrides the internal definition shown above, and limits the size of any mail message that is delivered to files to 1 megabyte:

>     M*file*, P=[FILE], M=1000000, F=9DEFMPloqsu, T=DNS/RFC822/X-Unix, A=FILE $u

Note that any equate that does not default to zero (such as the `P=`, `F=`, `T=`, and `A=` equates) needs to be copied to this configuration file declaration, or the original value will be lost.

A similar change in definition for the m4 configuration of V8 sendmail would look like this:

>     LOCAL_CONFIG
>     M*file*, P=[FILE], M=1000000, F=9DEFMPloqsu, T=DNS/RFC822/X-Unix, A=FILE $u

### 30.5.2 The error Delivery Agent

All versions of sendmail define a special internal delivery agent called `error` that is designed to aid in the issuance of error messages. It is always available for use in rule sets 0 and 5, and the `check_...` rule sets and cannot be defined with an `M` command.

Beginning with V8.7, the form for using the `error` agent in the RHS of a rule looks like this:

>     R...          $#error $@ dsn  $: text of error message here

In general terms, the text following the `$:` is the actual error message that will be included in bounced mail and sent back to a connecting SMTP host. For example, the following rule in rule set 0 would cause all mail to the local user George Washington to bounce:

>     RGeorge.Washington       $#error $: George Washington doesn't sleep here anymore

with an error message like this:

>     553 <george.washington>... George Washington doesn't sleep here anymore

#### 30.5.2.1 The $@ dsn part

Delivery Status Notification (DSN, see RFC1893) provides a means for conveying the status of a message's delivery. That status is conveyed in the form of a numeric triple (so as to be easily parseable by machines). This triple is included in the "machine readable" part of bounced messages:

>     success.category.detail

Each part of the triple is separated from the others with dot characters. There may be no space around the dots. The parts are numeric, and the meanings are as follows: `success` Was the overall delivery attempt a success? This part can be one of three digits. A 2 means that the message was successfully delivered. A 4 means that delivery has failed so far but it may succeed in the future. A 5 means that delivery failed (permanently). `category` Failure can be caused by several categories of problem. For example, if this `category` is a 1, it means that there was a problem with the address. If it is a 4 it means that there was a problem with the network. `detail` The `detail` further illuminates the `category`. For example, a category of 1 (address problem) might be caused by a detail of 1 (no such mailbox), or 4 (ambiguous address).

The `$@` part of the `error` delivery agent declaration specifies a DSN code that is appropriate for the error.

>     R...          $#error $@ success.category.detail  $: text of error message here

The sendmail program sets its exit(2) value according to the `success.category.detail` specified. Table 30.6 shows the relationship between those DSN codes on the left and UNIX exit(2) values on the right. Note that the exit values are defined in <sysexits.h>, and note that `success` codes of 2 and 4 completely ignore any `category` and `detail` that may be present (that is, 2.anything.anything marks successful delivery). If `$@` lists a code that is not in the table, the default exit value is EX_CONFIG. To illustrate, observe that `8.7.1` (see RFC1893) will exit with EX_DATAERR because it corresponds to the `*.7.*` in the table.

Table 30.6: DSN Versus exit(2) Values with $@ of $#error
DSN | exit(2) | String | Meaning
--- | --- | --- | ---
`2.*.*` | EX_OK |  | Successful delivery
`4.*.*` | EX_TEMPFAIL | tempfail | Temporary failure, will keep trying
`*.0.*` | EX_UNAVAILABLE | unavailable | Other address status
`*.1.0` | EX_DATAERR |  | Other address status
`*.1.1` | EX_NOUSER | nouser | Address is that of a bad mailbox
`*.1.2` | EX_NOHOST | nohost | Address of recipient is bad
`*.1.3` | EX_USAGE | usage | Address of recipient has bad syntax
`*.1.4` | EX_UNAVAILABLE | unavailable | Address is ambiguous
`*.1.5` | EX_OK |  | Address of destination is valid
`*.1.6` | EX_NOUSER | nouser | Address has moved, no forwarding
`*.1.7` | EX_USAGE | usage | Address of sender has bad syntax
`*.1.8` | EX_NOHOST | nohost | Address of sender is bad
`*.2.0` | EX_UNAVAILABLE | unavailable | Mailbox status is undefined
`*.2.1` | EX_UNAVAILABLE | unavailable | Mailbox disabled
`*.2.2` | EX_UNAVAILABLE | unavailable | Mailbox full
`*.2.3` | EX_DATAERR |  | Mailbox is too small or message is too large
`*.2.4` | EX_UNAVAILABLE | unavailable | Mailbox led to mail list expansion problems
`*.3.*` | EX_OSERR |  | Operating system error
`*.4.0` | EX_IOERR |  | Network error is undefined
`*.4.1` | EX_TEMPFAIL | tempfail | Network: no answer from host
`*.4.2` | EX_IOERR |  | Network bad connection
`*.4.3` | EX_TEMPFAIL | tempfail | Network routing failure
`*.4.4` | EX_PROTOCOL | protocol | Network unable to route
`*.4.5` | EX_TEMPFAIL | tempfail | Network congestion
`*.4.6` | EX_CONFIG | config | Network routing loop detected
`*.4.7` | EX_UNAVAILABLE | unavailable | Network delivery time expired
`*.5.*` | EX_PROTOCOL | protocol | Protocol failure
`*.6.*` | EX_UNAVAILABLE | unavailable | Message contents bad or media failure
`*.7.*` | EX_DATAERR |  | Security: general security rejection
else | EX_CONFIG | config | Internal configuration error

To illustrate, consider the need to reject all mail from a particular host (say evilhost.domain). We want to reject that host for security reasons, so we might set up a rule like this:

>     R$* < @ evilhost.domain > $*        $#error $@ 5.7.1 $: You are bad, go away

Here, the number following the `$@` contains a dot, so it is interpreted as a DSN status expression. The `.7.` in it causes sendmail to set its exit valut to EX_DATAERR, and the `5.7.1` is defined in RFC1893 as meaning "Permanent failure, delivery not authorized, message refused."

If the number following the `$@` does not contain a dot, sendmail sets its exit(2) value to that number. For example, the below results in the same exit(2) value as the above but gives a less informative DSN in the bounce message:

>     R$* < @ evilhost.domain > $*        $#error $@ 65 $: You are bad, go away

>                                         the value of EX_DATAERR from <sysexits.h>

If the expression following the `$@` is non-numeric, sendmail looks up the string and translates a known one into the appropriate exit(2) value. The recognized strings are listed in the third column of Table 30.6. For example, the following will cause sendmail to exit with an EX_UNAVAILABLE value:

>     R$* < @ evilhost.domain > $*        $#error $@ unavailable $: You are bad, go away

If the string following the `$@` is not one of those listed in the table, the default exit(2) value becomes EX_UNAVAILABLE.

### 30.5.3 The $: Part

Recall that the text of the error message following the `$:` is used as a literal error message. That is, this `$:` part:

>     R...          $#error  $: george doesn't sleep here anymore

produces this error for the address george@wash.dc.gov:

>     553 <george@wash.dc.gov>... george doesn't sleep here anymore

Here the 553 is an SMTP code (see RFC821). If you want a different SMTP code issued, you may do so by prefixing the `$:` part with it:

>     R...          $#error  $: 421 george doesn't sleep here anymore

If three digits followed by a space are present as a prefix, those digits are used as the SMTP reply code when sendmail is speaking SMTP. If no digits and space prefix the text, the default SMTP reply code is 553.

A few SMTP codes that are useful with `$:` are listed in Table 30.7. The complete list of all SMTP codes can be found in RFC821.

Table 30.7: Useful SMTP Codes for Use with $:
Code | Meaning
--- | ---
421 | Service not available (drop the message)
553 | Requested action not taken (bounce the message)

Note that you should restrict yourself to the small set of codes that may legally be returned to the RCPT SMTP command. Also note that any DSN code that is specified in the `$@` part must avoid conflicting with the meaning of the SMTP code. For example, the following construct is wrong and should be avoided:

>     R...          $#error $@ 2.1.1 $: 553 ...      avoid such conflicts

Here, the DSN `2.1.1` means that delivery was successful, whereas the SMTP `553` means that delivery failed and the message bounced.

30.4 The Equates |  | 30.6 How Executed